/*
 * sleepy.c 
 */ 


#include <linux/init.h>
#include <linux/module.h>

#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/types.h>

#include <linux/wait.h>

static int sleepy_major = 0;

static DECLARE_WAIT_QUEUE_HEAD(wq);
/*
 * wait_queue_head_t my_queue;
 * init_waitqueue_head(&my_queue);
 */
static int flag = 0;

static ssize_t sleepy_read(struct file *filp, char __user *buf, size_t count, loff_t *pos)
{
	printk(KERN_INFO "process %i (%s) is going to sleep\n", current->pid, current->comm);
	wait_event_interruptible(wq, flag != 0);
	flag = 0;
	printk(KERN_INFO " %i (%s) wakes up now\n", current->pid, current->comm);
	return 0;
}


static ssize_t sleepy_write(struct file *filp, const char __user *buf, size_t count, loff_t *pos)
{
	printk(KERN_INFO "process %i (%s) wakes up readers...\n", current->pid, current->comm);
	flag = 1;
	wake_up_interruptible(&wq);
	return count;
}




static struct file_operations sleepy_fops = {
	.owner = THIS_MODULE,
	.read = sleepy_read,
	.write = sleepy_write
};

static int sleepy_init(void)
{
	int ret;
	
	ret = register_chrdev(sleepy_major, "sleepy", &sleepy_fops);
	if (ret < 0)
		return ret;
	if (sleepy_major == 0)
		sleepy_major = ret;
	return 0;
}

static void sleepy_cleanup(void)
{
	unregister_chrdev(sleepy_major, "sleepy");
}

module_init(sleepy_init);
module_exit(sleepy_cleanup);

MODULE_LICENSE("GPL");
